/////////////////////////////////////////////////////////////////////////////
// This file is part of the "Java-DAP" project, a Java implementation
// of the OPeNDAP Data Access Protocol.
//
// Copyright (c) 2007 OPeNDAP, Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
/////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections;
using System.IO;
using NDODS.DAP.BaseTypes;
using NDODS.DAP.Exceptions;
using NDODS.DAP.XMLParser;

namespace NDODS.DAP
{
    /// <summary> Contains methods used only by the OPeNDAP constructor classes
    /// (<code>DStructure</code>, <code>DSequence</code>, <code>DGrid</code>, and
    /// <code>DList</code>).
    /// 
    /// </summary>
    /// <author>  jehamby
    /// </author>
    /// <version>  $Revision: 15901 $
    /// </version>
    /// <seealso cref="DStructure">
    /// </seealso>
    /// <seealso cref="DSequence">
    /// </seealso>
    /// <seealso cref="DGrid">
    /// </seealso>
    [Serializable]
    public abstract class DConstructor : BaseType
    {
        /// <summary> Return an Enumeration that can be used to iterate over all of the
        /// members of the class. Each implementation must define what this means.
        /// The intent of this method is to support operations on all members of a
        /// Structure, Seqeunce or Grid that can be performed equally. So it is
        /// not necessary that this methods be usable, for example, when the
        /// caller needs to know that it s dealing with the Array part of a grid.
        /// 
        /// </summary>
        /// <returns> An Enumeration object.
        /// </returns>
        public abstract IEnumerator Variables { get; }

        //    /** A <code>Vector</code> of OPeNDAP BaseTypes to be used by my children */
        //    protected Vector vars;


        /// <summary> Constructs a new <code>DConstructor</code> with the given name.
        /// 
        /// </summary>
        /// <param name="n">The name of the variable.
        /// </param>
        public DConstructor(String n) : base(n) {}

        /// <summary> Adds a variable to the container.
        /// 
        /// </summary>
        /// <param name="v">   the variable to add.
        /// </param>
        /// <param name="part">The part of the constructor data to be modified.
        /// </param>
        public abstract void addVariable(BaseType v, int part);

        /// <summary> Adds a variable to the container.  Same as <code>addVariable(v, 0)</code>.
        /// 
        /// </summary>
        /// <param name="v">the variable to add.
        /// </param>
        public void addVariable(BaseType v) {
            addVariable(v, 0);
        }

        /// <summary> Gets the named variable.
        /// 
        /// </summary>
        /// <param name="name">the name of the variable.
        /// </param>
        /// <returns> the named variable.
        /// </returns>
        /// <throws>  NoSuchVariableException if the named variable does not </throws>
        /// <summary>                                 exist in this container.
        /// </summary>
        public abstract BaseType getVariable(String name);

        /// <summary> Gets the indexed variable. For a DGrid the index 0 returns the <code>DArray</code> and
        /// indexes 1 and higher return the associated map <code>Vector</code>s.
        /// 
        /// </summary>
        /// <param name="index">the index of the variable in the <code>Vector</code> Vars.
        /// </param>
        /// <returns> the named variable.
        /// </returns>
        /// <throws>  NoSuchVariableException if the named variable does not </throws>
        /// <summary>                                 exist in this container.
        /// </summary>
        public abstract BaseType getVar(int index);


        /// <summary> </summary>
        /// <param name="bt">The BasType object to Search.
        /// </param>
        /// <returns> true if some child of the passed BaseType has attributes
        /// </returns>
        /// <opendap.ddx.experimental>  </opendap.ddx.experimental>
        protected internal virtual bool someChildHasAttributes(BaseType bt) {
            bool foundit = false;

            if (bt.HasAttributes())
                return (true);

            if (bt is DConstructor) {
                IEnumerator e = ((DConstructor) bt).Variables;

                //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
                while (e.MoveNext()) {
                    //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                    BaseType thisBT = (BaseType) e.Current;

                    foundit = foundit || someChildHasAttributes(thisBT);
                }
            }

            return (foundit);
        }

        /// <summary> </summary>
        /// <param name="pw">Where to Print
        /// </param>
        /// <param name="pad">Padding for iondentation (makes the output easier for humans
        /// to Read).
        /// </param>
        /// <param name="constrained">If true then only projected variables (and their
        /// Attributes) will be printed.
        /// </param>
        /// <opendap.ddx.experimental>  </opendap.ddx.experimental>
        public override void PrintXML(StreamWriter pw, String pad, bool constrained) {
            IEnumerator e = AttributeNames.GetEnumerator();
            IEnumerator ve = Variables;

            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            bool hasAttributes = e.MoveNext();
            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            bool hasVariables = ve.MoveNext();

            pw.Write(pad + "<" + TypeName);
            if (Name != null) {
                pw.Write(" name=\"" + DDSXMLParser.normalizeToXML(ClearName) + "\"");
            }


            if (hasAttributes || hasVariables) {
                //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
                pw.WriteLine(">");

                //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
                while (e.MoveNext()) {
                    //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                    String aName = (String) e.Current;

                    try {
                        Attribute a = GetAttribute(aName);
                        a.printXML(pw, pad + "\t", constrained);
                    }
                    catch (NoSuchAttributeException nsae) {
                        // Don't do a thing...
                    }
                }

                //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
                while (ve.MoveNext()) {
                    //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                    BaseType bt = (BaseType) ve.Current;
                    bt.PrintXML(pw, pad + "\t", constrained);
                }

                //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
                pw.WriteLine(pad + "</" + TypeName + ">");
            }
            else {
                //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
                pw.WriteLine("/>");
            }
        }
    }
}